package top.revery.account.controller;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayFundTransToaccountTransferModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayFundTransToaccountTransferRequest;
import com.alipay.api.response.AlipayFundTransToaccountTransferResponse;

import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.RestController;
import top.revery.account.dto.*;
import top.revery.account.service.LogUserService;
import top.revery.account.service.WxService;
import top.revery.account.service.ZhifuBaoService;
import top.revery.account.utils.FeignServiceMapping;
import top.revery.api.api.payWallet.ILogUserApi;
import top.revery.api.config.PayType;
import top.revery.api.config.UserPageData;
import top.revery.api.config.ZhifubaoConfig;
import top.revery.api.entity.payWallet.BaseAliPayLog;
import top.revery.api.entity.payWallet.BaseAliayBD;
import top.revery.api.entity.payWallet.BaseLogUser;

import top.revery.api.entity.user.BaseUserInfo;
import top.revery.api.util.*;


import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.*;

/**
 * @author denghao
 * @title
 * @package
 * @date 2019/12/17 14:06
 */
@Slf4j
@RestController
public class PayWalletController implements ILogUserApi {
    private ExecutorService executorService = Executors.newFixedThreadPool(20);
    String orderNumber = PayCommonUtil.getRandomString(32);
    @Autowired
    private LogUserDto logUserDto;
    @Autowired
    private LogUserService logUserService;
    @Autowired
    private ZhifuBaoService zhifuBaoService;
    @Autowired
    private WxService wxService;
    @Autowired
    private AliPayLogDto aliPayLogDto;
    private String out_trade_no = "";

    @Autowired
    private AliayBDDto aliayBDDto;

    /*  FeignServiceMapping.userService;

     FeignServiceMapping.companyService;
     FeignServiceMapping.kolService;
  */
    //分页查询
    @Override
    public UserPageData getList(int pageNum, int pageSize, Map map) {

        Page<BaseLogUser> pageList = logUserService.findPage(pageNum, pageSize, map);
        UserPageData userPageData = new UserPageData();
        userPageData.list = pageList.getContent();
        userPageData.rows = pageList.getTotalElements();
        return userPageData;
    }

    //保存
    @Override
    public BaseLogUser save(BaseLogUser baseLogUser) {
        try {
            return logUserDto.save(baseLogUser);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

    //根据id查询
    @Override
    public BaseLogUser findById(Long id) {

        try {
            Optional<BaseLogUser> byId = logUserDto.findById(id);
            if (byId.isPresent()) {
                return byId.get();
            } else {
                throw new Exception("记录不存在!");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //用户充值
    @Override
    @GlobalTransactional
    public String rechargeMoney(BigDecimal money,PayType payType) throws Exception {

        if (money.equals(0) || money == null) {
            throw new Exception("请输入充值金额！");
        }

          if(payType== PayType.ZFB){
        return zhifuBaoService.pay(money);

          }else {
       return wxService.wxpay(money);

        //  return  null;
          }


    }

    @Override
    @GlobalTransactional
    public String alipayNotify(HttpServletRequest request, Long id) throws Exception{
        log.info("==================支付宝异步返回支付结果开始");
        Map<String, String[]> map = request.getParameterMap();
        Map<String, String> paramsMap = new HashMap<>();
        map.forEach((key, values) -> {
            String strs = "";
            for (String value : values) {
                strs = strs + value;
            }
            System.out.println(("key值为" + key + "value为：" + strs));
            paramsMap.put(key, strs);
        });
        System.out.println(paramsMap);

        //SDK验证签名
        try {
            boolean b = AlipaySignature.rsaCheckV1(paramsMap, ZhifubaoConfig.alipay_public_key, ZhifubaoConfig.charset, ZhifubaoConfig.sign_type);
//            boolean b = AlipaySignature.rsaCheckV1(paramsMap, ZhifubaoConfig.alipay_public_key, ZhifubaoConfig.charset);
            if (b == false) {
                log.info("****************************************验签失败*******************************************");
                BaseAliPayLog baseAliPayLog = new BaseAliPayLog();
                baseAliPayLog.setApp_id(paramsMap.get("app_id"));
                baseAliPayLog.setMoney(paramsMap.get("total_amount"));
                baseAliPayLog.setOut_trade_no(paramsMap.get("out_trade_no"));
                // baseAliPayLog.setSign(paramsMap.get("sign"));
                baseAliPayLog.setTrade_no(paramsMap.get("trade_no"));
                baseAliPayLog.setTrade_status("failture");
                baseAliPayLog.setAddTime(new Timestamp(new Date().getTime()));
                aliPayLogDto.save(baseAliPayLog);
                return "failture";
            }

            log.info("支付宝回调签名认证成功");

            //记录充值支付的记录
            BaseAliPayLog baseAliPayLog = new BaseAliPayLog();
            baseAliPayLog.setApp_id(paramsMap.get("app_id"));
            baseAliPayLog.setMoney(paramsMap.get("total_amount"));
            baseAliPayLog.setOut_trade_no(paramsMap.get("out_trade_no"));
            // baseAliPayLog.setSign( paramsMap.get("sign"));
            baseAliPayLog.setTrade_no(paramsMap.get("trade_no"));
            baseAliPayLog.setTrade_status("success");
            baseAliPayLog.setAddTime(new Timestamp(new Date().getTime()));
            aliPayLogDto.save(baseAliPayLog);

            BaseUserInfo baseUserInfo = FeignServiceMapping.userService.findById(id).getBaseUserInfo();
            baseUserInfo.setTotalMoney(baseUserInfo.getTotalMoney().add(new BigDecimal(paramsMap.get("total_amount"))));
            FeignServiceMapping.userService.save(baseUserInfo);
            BaseLogUser baseLogUser = new BaseLogUser();
            baseLogUser.setUserId(id);
            baseLogUser.setType(0);
            baseLogUser.setUserType(1);
            baseLogUser.setMoney(new BigDecimal(paramsMap.get("total_amount")));
            baseLogUser.setAddTime(new Timestamp(new Date().getTime()));
            logUserDto.save(baseLogUser);
            return "success";

        } catch (AlipayApiException e) {
            e.printStackTrace();
            System.out.println("*********************验签失败********************");
            return "failture";
        }
    }


    @Override
    @GlobalTransactional
    public String wxNotify(HttpServletRequest request,Long id) throws Exception {
        log.info("==================微信异步返回支付结果开始");
        InputStream inputStream;
        StringBuffer sb = new StringBuffer();
        inputStream = request.getInputStream();
        String s;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        while ((s = in.readLine()) != null) {
            sb.append(s);
        }
        in.close();
        inputStream.close();
        System.out.println("sb:" + sb.toString());

        //解析xml成map
        Map<String, String> map = new HashMap<String, String>();
        try {
            Document doc = DocumentHelper.parseText(sb.toString());
            Element rootElt = doc.getRootElement();
            System.out.println("根节点：" + rootElt.getName());
            Iterator iter = rootElt.elementIterator("head");// 获取根节点下的子节点head
            // 遍历head节点
            while (iter.hasNext()) {
                Element recordEle = (Element) iter.next();
                String title = recordEle.elementTextTrim("title"); // 拿到head节点下的子节点title值
                System.out.println("title:" + title);
                map.put("title", title);
                Iterator iters = recordEle.elementIterator("script"); // 获取子节点head下的子节点script
                // 遍历Header节点下的Response节点
                while (iters.hasNext()) {
                    Element itemEle = (Element) iters.next();
                    String username = itemEle.elementTextTrim("username"); // 拿到head下的子节点script下的字节点username的值
                    String password = itemEle.elementTextTrim("password");
                    System.out.println("username:" + username);
                    System.out.println("password:" + password);
                    map.put("username", username);
                    map.put("password", password);
                }
            }
            Iterator iterss = rootElt.elementIterator("body"); ///获取根节点下的子节点body
            // 遍历body节点
            while (iterss.hasNext()) {
                Element recordEless = (Element) iterss.next();
                String result = recordEless.elementTextTrim("result"); // 拿到body节点下的子节点result值
                System.out.println("result:" + result);
                Iterator itersElIterator = recordEless.elementIterator("form"); // 获取子节点body下的子节点form
                // 遍历Header节点下的Response节点
                while (itersElIterator.hasNext()) {
                    Element itemEle = (Element) itersElIterator.next();
                    String banlce = itemEle.elementTextTrim("banlce"); // 拿到body下的子节点form下的字节点banlce的值
                    String subID = itemEle.elementTextTrim("subID");
                    System.out.println("banlce:" + banlce);
                    System.out.println("subID:" + subID);
                    map.put("result", result);
                    map.put("banlce", banlce);
                    map.put("subID", subID);
                }
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //过滤空 设置 TreeMap
        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        Iterator<String> it = map.keySet().iterator();
        while (it.hasNext()) {
            String parameter = it.next();
            String parameterValue = map.get(parameter);

            String v = "";
            if (null != parameterValue) {
                v = parameterValue.trim();
            }
            packageParams.put(parameter, v);
        }

        if (PayCommonUtil.isTenpaySign(packageParams)) { // 验证通过
            if ("SUCCESS".equals((String) packageParams.get("result_code"))) {
                System.out.println("验证通过");
                //记录

            } else {
                System.out.println("支付失败");
            }
        } else {
            System.out.println("验证未通过");
        }

        return "SUCCESS";

    }


    //提现
    @Override
    @GlobalTransactional
    public BaseAliayBD drawMoney(BigDecimal money, String account, String userName, Long id) throws Exception {
        log.info("==================提现开始");
        if (money.equals(0) || money == null) {
            throw new Exception("请输入提现金额！");
        }
        BaseUserInfo userIn = FeignServiceMapping.userService.findById(id).getBaseUserInfo();
        if (userIn.getTotalMoney().compareTo(money) < 0) {
            throw new Exception("提现金额不能大于用户总金额数！");
        }
        Timestamp endDrawTime = logUserDto.findTime(id);
        Timestamp timestamp0  = new Timestamp(System.currentTimeMillis());
        Calendar c = Calendar.getInstance();
        c.setTime(endDrawTime);
        c.set(Calendar.DATE, 7);
        Timestamp time1 = new Timestamp(c.getTimeInMillis());
        if(time1.before(timestamp0)){
            throw new Exception("本周您已提现，一周只能提一次现！");
        }
        BaseAliayBD baseAliayBD = new BaseAliayBD();
        baseAliayBD.setUserId(id);
        baseAliayBD.setAccount(account);
        baseAliayBD.setMoney(money);
        baseAliayBD.setName(userName);
        baseAliayBD.setType(0);
        baseAliayBD.setAddTime(new Timestamp(new Date().getTime()));
        return aliayBDDto.save(baseAliayBD);
    }

   //提现转账
        @Override
      //  @GlobalTransactional
        public Map<String,String> transfer(BaseAliayBD baseAliayBD) throws Exception {
        //定义参数
        String userName = baseAliayBD.getName();
        String account = baseAliayBD.getAccount();
        BigDecimal money = baseAliayBD.getMoney();
        if(baseAliayBD.getType()!=0){
            throw new Exception("对不起!请求提现已提现或拒绝!");
        }
        if(baseAliayBD.getAuditor()==null){
            throw new Exception("请填写审核人姓名!");
        }

        Map<String,String> map=new HashMap<String,String>();
        AlipayClient alipayClient = new DefaultAlipayClient(ZhifubaoConfig.URL, ZhifubaoConfig.App_id,
                ZhifubaoConfig.RSA_PRIVATE_KEY, ZhifubaoConfig.FORMAT, ZhifubaoConfig.charset, ZhifubaoConfig.alipay_public_key,
                ZhifubaoConfig.sign_type);
// 设置请求参数
 AlipayFundTransToaccountTransferRequest alipayRequest = new AlipayFundTransToaccountTransferRequest();
 AlipayFundTransToaccountTransferModel model =new AlipayFundTransToaccountTransferModel();
       /* map.put("payee_type", "ALIPAY_LOGONID");
        map.put("payee_account",account);
        map.put("amount", money.toString());
        map.put("payer_show_name", "恒生平台用户提现");
        map.put("payee_real_name",userName);
        map.put("remark", "支付宝转账提现");
       alipayRequest.setBizContent(map.toString());*/
        model.setOutBizNo(IdUtil.orderNumber());
        model.setPayeeType("ALIPAY_LOGONID");
        model.setPayeeAccount(account);
        model.setPayeeRealName(userName);
        model.setPayerShowName("恒生平台用户提现");
        model.setAmount(money.toString());
        model.setRemark("支付宝转账提现");
        alipayRequest.setBizModel(model);
        AlipayFundTransToaccountTransferResponse response=null;
        try {
            response = alipayClient.execute(alipayRequest);
            System.out.println(JSON.toJSONString(response));
            if("10000".equals(response.getCode())){
                map.put("success", "true");
                map.put("des", "转账成功");
                baseAliayBD.setType(1);
                baseAliayBD.setMark("您已提现成功,请注意查收提现金额!");
                baseAliayBD.setAddTime(new Timestamp(new Date().getTime()));
                aliayBDDto.save(baseAliayBD);
                BaseUserInfo baseUserInfo = FeignServiceMapping.userService.findById(baseAliayBD.getUserId()).getBaseUserInfo();
                if(baseUserInfo.getUserType()==0){
                baseUserInfo.setTotalMoney(baseUserInfo.getTotalMoney().divide(money));
                baseUserInfo.setTotalCashMoney(baseUserInfo.getTotalCashMoney().add(money));
                FeignServiceMapping.userService.save(baseUserInfo);
                    BaseLogUser baseLogUser = new BaseLogUser();
                    baseLogUser.setUserId(baseAliayBD.getUserId());
                    baseLogUser.setType(1);
                    baseLogUser.setUserType(0);
                    baseLogUser.setMoney(money);
                    baseLogUser.setAddTime(new Timestamp(new Date().getTime()));
                    logUserDto.save(baseLogUser);
                }else {
                    baseUserInfo.setTotalMoney(baseUserInfo.getTotalMoney().divide(money));
                    FeignServiceMapping.userService.save(baseUserInfo);
                    BaseLogUser baseLogUser = new BaseLogUser();
                    baseLogUser.setUserId(baseAliayBD.getUserId());
                    baseLogUser.setType(1);
                    baseLogUser.setUserType(1);
                    baseLogUser.setMoney(money);
                    baseLogUser.setAddTime(new Timestamp(new Date().getTime()));
                    logUserDto.save(baseLogUser);
                }

            }else{
                log.info("调用支付宝转账提现接口成功,但提现失败");
                map.put("success", "false");
                map.put("des", response.getSubMsg());
                baseAliayBD.setType(2);
                baseAliayBD.setMark("很抱歉!您的提现失败!请检查是否账户与名字不匹配!");
                baseAliayBD.setAddTime(new Timestamp(new Date().getTime()));
                aliayBDDto.save(baseAliayBD);
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
            map.put("success", "false");
            map.put("des", "转账失败！");
        }
        return map;
    }

    //假如有提现记录则直接返回在表单中
    @Override
    public BaseAliayBD getById(Long id) throws Exception {
        try {
            Optional<BaseAliayBD> byId = aliayBDDto.findById(id);
            if (byId.isPresent()) {
                return byId.get();
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
